package com.cts.tmall.cfg;

import com.alibaba.fastjson.JSON;
import com.cts.tmall.com.message.BaseRsp;
import com.cts.tmall.com.message.RspCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Arrays;
import java.util.List;

/**
 * SpringMVC 配置
 *
 * @author leibing.song
 * @since 2020-07-28
 */
@Configuration
@ServletComponentScan("com.lfm.admin.app")
public class WebConfig implements WebMvcConfigurer {

  @Override
  public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
    resolvers.add(0, (request, response, handler, ex) -> new ModelAndView("forward:/api/error", Exception.class.getSimpleName().toLowerCase(), ex));
  }

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedOrigins("*")
      .allowedMethods("POST", "GET", "PUT", "DELETE")
      .maxAge(3600)
      .allowCredentials(true);
  }

  @Configuration
  public static class VueRouterConfig implements ErrorPageRegistrar {
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
      registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
    }
  }

  @Slf4j
  @Configuration
  @ControllerAdvice("com.cts.tmall.app.controller")
  public static class JsonAdviceConfig implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
      return Boolean.TRUE;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
      if (body == null || !Arrays.asList(String.class, BaseRsp.class, byte[].class).contains(body.getClass())) {
        body = new BaseRsp()
          .setRspCode(RspCode.SUCCESS.getRspCode())
          .setRspDesc(RspCode.SUCCESS.getRspDesc())
          .setRspData(body);
      }
      log.info("请求地址：{}  返回结果：{}", request.getURI(), JSON.toJSONString(body));
      return body;
    }
  }
}
